package cn.powerone.scm.controller;

import java.util.Date;
import java.util.List;
import java.util.Map;

import cn.powerone.common.annotation.Excel;
import cn.powerone.scm.domain.*;
import cn.powerone.scm.service.*;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.powerone.common.annotation.Log;
import cn.powerone.common.core.controller.BaseController;
import cn.powerone.common.core.domain.AjaxResult;
import cn.powerone.common.enums.BusinessType;
import cn.powerone.common.utils.poi.ExcelUtil;
import cn.powerone.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 出入库请求记录Controller
 * 
 * @author PowerOne
 * @date 2025-07-27
 */
@RestController
@RequestMapping("/scm/request")
public class ScmInventoryLogRequestController extends BaseController
{
    @Autowired
    private IScmInventoryLogRequestService scmInventoryLogRequestService;
    @Autowired
    private IScmInventoryLogService scmInventoryLogService;

    @Autowired
    private IScmInventoryService scmInventoryService;

    @Autowired
    private IScmSupplierOrderItemsService scmSupplierOrderItemsService;

    @Autowired
    private IScmCustomerOrderItemsService scmCustomerOrderItemsService;
    /**
     * 查询出入库请求记录列表
     */
    @PreAuthorize("@ss.hasPermi('scm:request:list')")
    @GetMapping("/list")
    public TableDataInfo list(ScmInventoryLogRequest scmInventoryLogRequest)
    {
        startPage();
        List<ScmInventoryLogRequest> list = scmInventoryLogRequestService.selectScmInventoryLogRequestList(scmInventoryLogRequest);
        return getDataTable(list);
    }

    /**
     * 导出出入库请求记录列表
     */
    @PreAuthorize("@ss.hasPermi('scm:request:export')")
    @Log(title = "出入库请求记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ScmInventoryLogRequest scmInventoryLogRequest)
    {
        List<ScmInventoryLogRequest> list = scmInventoryLogRequestService.selectScmInventoryLogRequestList(scmInventoryLogRequest);
        ExcelUtil<ScmInventoryLogRequest> util = new ExcelUtil<ScmInventoryLogRequest>(ScmInventoryLogRequest.class);
        util.exportExcel(response, list, "出入库请求记录数据");
    }

    /**
     * 获取出入库请求记录详细信息
     */
    @PreAuthorize("@ss.hasPermi('scm:request:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        ScmInventoryLogRequest scmInventoryLogRequest =    scmInventoryLogRequestService.selectScmInventoryLogRequestById(id);

        ScmInventoryLog log = new ScmInventoryLog();
        log.setInventoryLogRequestId(id);
        List<ScmInventoryLog> list= scmInventoryLogService.selectScmInventoryLogList(log);

        scmInventoryLogRequest.setScmInventoryLogList(list);
        return success(scmInventoryLogRequest);
    }

    /**
     * 新增出入库请求记录
     */
    @PreAuthorize("@ss.hasPermi('scm:request:add')")
    @Log(title = "出入库请求记录", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody ScmInventoryLogRequest scmInventoryLogRequest) {


        // 先保存请求，获取生成的ID
        //设置scmInventoryLogRequest.setInventoryLogRequestId(requestId);

        boolean outLib = false;
        String dateStr = new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date());
        if (scmInventoryLogRequest.getInOutIndicator().equals(1L) ){
            scmInventoryLogRequest.setIdName("RK" + dateStr);
            outLib = false;
        }else if (scmInventoryLogRequest.getInOutIndicator().equals(2L)){
            scmInventoryLogRequest.setIdName("CK" + dateStr);
            outLib = true;
        }
        scmInventoryLogRequestService.insertScmInventoryLogRequest(scmInventoryLogRequest);

        Long requestId = scmInventoryLogRequest.getId();

        List<ScmInventoryLog> logList = scmInventoryLogRequest.getScmInventoryLogList();
        if (logList != null && !logList.isEmpty()) {
            for (ScmInventoryLog log : logList) {
                // 1. 查询ScmInventory 检查当前入库的产品在库存表中是否存在。
                ScmInventory inventory = scmInventoryService.findByProductIdAndWarehouseLocationId(
                        log.getProductId(), log.getWarehouseLocationId());

                if (inventory == null) {
                    if (outLib){
                        // 出库时，库存记录不存在，不能出库，抛出异常
                        throw new RuntimeException("产品ID " + log.getProductId() + " 在仓库位置ID " + log.getWarehouseLocationId() + " 的库存记录不存在，不能出库");
                    }else {
                        // 2. 如果不存在，则新增一条库存记录，初始数量为本次入库数量
                        inventory = new ScmInventory();
                        inventory.setProductId(log.getProductId());
                        inventory.setWarehouseLocationId(log.getWarehouseLocationId());
                        inventory.setCurrentQuantity(log.getChangeQuantity());
                        inventory.setAvailableQuantity(log.getChangeQuantity());
                        inventory.setAllocatedQuantity(0L);

                        inventory.setMinimumStock(0L);
                        inventory.setMaximumStock(999L);
                        inventory.setInventoryStatus(1L);
                        inventory.setLastUpdateTime(new Date());
                        inventory.setUpdatedAt(new Date());
                        inventory.setUpdatedBy(log.getUpdateBy());
                        inventory.setUpdatedById(log.getCreatedById());
                        // 5. 保存库存记录
                        scmInventoryService.insertScmInventory(inventory);
                    }

                }else{
                    if (outLib){
                        // 4. 如果存在，则更新库存记录，数量为当前库存数量加上本次入库数量
                        inventory.setCurrentQuantity(inventory.getCurrentQuantity() - log.getChangeQuantity());
                        inventory.setAvailableQuantity(inventory.getAvailableQuantity() - log.getChangeQuantity());
                        // 5. 保存库存记录
                        scmInventoryService.updateScmInventory(inventory);

                    }else{
                        // 4. 如果存在，则更新库存记录，数量为当前库存数量加上本次入库数量
                        inventory.setCurrentQuantity(inventory.getCurrentQuantity() + log.getChangeQuantity());
                        inventory.setAvailableQuantity(inventory.getAvailableQuantity() + log.getChangeQuantity());
                        // 5. 保存库存记录
                        scmInventoryService.updateScmInventory(inventory);
                    }
                }



                // 6. 设置ScmInventoryLog字段
                if (outLib) {
                    //出库
                    log.setInventoryId(inventory.getId());
                    log.setInventoryLogRequestId(requestId);

                    //需要设置beforeQuantity, 需要查找InventoryLog表，通过order_Id 和 product_Id 查找当前以入库总数量.
                    ScmCustomerOrderItemsWithOrderInfoVO item = new ScmCustomerOrderItemsWithOrderInfoVO();
                    item.setProductId(log.getProductId());
                    item.setOrderId(log.getOrderId());
                    List<ScmCustomerOrderItemsWithOrderInfoVO> list = scmCustomerOrderItemsService.selectScmSupplierOrderItemsListWithOrderInfo(item);
                    //from list to get beforeQuantity from quantityInLib
                    if (list != null && !list.isEmpty()) {
                        //因为上边inventory的数量已经减过了，所以这里需要加上
                        log.setBeforeQuantity(Long.valueOf(list.get(0).getAvailableInventory()+ log.getChangeQuantity()));
                        log.setOrderQuantityInLib(list.get(0).getQuantityOutLib() + log.getChangeQuantity());
                        log.setOrderTotalQuantity(list.get(0).getQuantity().longValue());
                        log.setOrderQuantityNotInLib(list.get(0).getQuantity().longValue() - log.getOrderQuantityInLib());

                        log.setBillStatus(1L); // 1-初始状态
                        log.setBillDueDate(null); // 由于是入库，所以不需要设置到期日
                        log.setBillDate(null);
                        log.setBillComments(null);
                        log.setBillRemarks(null);
                    } else {
                        log.setBeforeQuantity(0L);
                        log.setOrderQuantityInLib(0L);
                        log.setOrderTotalQuantity(0L);
                        log.setOrderQuantityNotInLib(0L);
                    }
                    log.setAfterQuantity(log.getBeforeQuantity() - log.getChangeQuantity());
                }else{
                    //入库
                    log.setInventoryId(inventory.getId());
                    log.setInventoryLogRequestId(requestId);

                    //需要设置beforeQuantity, 需要查找InventoryLog表，通过order_Id 和 product_Id 查找当前以入库总数量.
                    ScmSupplierOrderItemsWithOrderInfoVO item = new ScmSupplierOrderItemsWithOrderInfoVO();
                    item.setProductId(log.getProductId());
                    item.setOrderId(log.getOrderId());
                    List<ScmSupplierOrderItemsWithOrderInfoVO> list = scmSupplierOrderItemsService.selectScmSupplierOrderItemsListWithOrderInfo(item);
                    //from list to get beforeQuantity from quantityInLib
                    if (list != null && !list.isEmpty()) {
                        log.setBeforeQuantity(list.get(0).getAvailableInventory() - log.getChangeQuantity());
                        log.setOrderQuantityInLib(list.get(0).getQuantityInLib() + log.getChangeQuantity());
                        log.setOrderTotalQuantity(list.get(0).getQuantity().longValue());
                        log.setOrderQuantityNotInLib(list.get(0).getQuantity().longValue() - log.getOrderQuantityInLib());


                        log.setBillStatus(1L); // 1-初始状态
                        log.setBillDueDate(null); // 由于是入库，所以不需要设置到期日
                        log.setBillDate(null);
                        log.setBillComments(null);
                        log.setBillRemarks(null);
                    } else {
                        log.setBeforeQuantity(0L);
                        log.setOrderQuantityInLib(0L);
                        log.setOrderTotalQuantity(0L);
                        log.setOrderQuantityNotInLib(0L);
                    }
                    log.setAfterQuantity(log.getBeforeQuantity() + log.getChangeQuantity());
                }

                // 8. 保存ScmInventoryLog
                scmInventoryLogService.insertScmInventoryLog(log);

            }
        }
        return toAjax(1);
    }

    /**
     * 修改出入库请求记录
     */
    @PreAuthorize("@ss.hasPermi('scm:request:edit')")
    @Log(title = "出入库请求记录", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ScmInventoryLogRequest scmInventoryLogRequest)
    {
        return toAjax(scmInventoryLogRequestService.updateScmInventoryLogRequest(scmInventoryLogRequest));
    }

    /**
     * 删除出入库请求记录
     */
    @PreAuthorize("@ss.hasPermi('scm:request:remove')")
    @Log(title = "出入库请求记录", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(scmInventoryLogRequestService.deleteScmInventoryLogRequestByIds(ids));
    }



    /**
     * 上传XLS文件并生成计划
     */
    @PreAuthorize("@ss.hasPermi('scm:scmSupplierOrderItems:upload')")
    @PostMapping("/processXLSAndGenerateLibInPlan")
    public AjaxResult processXLSAndGenerateLibInPlan(@RequestParam("file") MultipartFile file) {
        try {
            List<Map<String, Object>> plans = scmInventoryLogRequestService.processXlsAndGenerateRequestInLibPlans(file);
            return AjaxResult.success(plans);
        } catch (Exception e) {
            return AjaxResult.error("Failed to process XLS file: " + e.getMessage());
        }
    }



    /**
     * 上传XLS文件并生成计划
     */
    @PreAuthorize("@ss.hasPermi('scm:scmSupplierOrderItems:upload')")
    @PostMapping("/processXLSAndGenerateLibOutPlan")
    public AjaxResult processXLSAndGenerateLibOutPlan(@RequestParam("file") MultipartFile file) {
        try {
            List<Map<String, Object>> plans = scmInventoryLogRequestService.processXlsAndGenerateRequestOutLibPlans(file);
            return AjaxResult.success(plans);
        } catch (Exception e) {
            return AjaxResult.error("Failed to process XLS file: " + e.getMessage());
        }
    }

}
